using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using GTA;
using GTA.Native;
using GTA.UI;

namespace CustomPeds;

[Serializable]
public class Skin
{
    public enum PedComponents { FACE, HEAD, HAIR, TORSO, LEGS, HANDS, FEET, ACCESSORIES, TORSO3, TASKS, TEXTURES, TORSO2 }
    public enum PedProps { HATS = 0, GLASSES = 1, EARRINGS = 2, WristAccessories1 = 6, WristAccessories2 = 7 }
    public enum PedHeadOverlay { Blemishes, Beard, Eyebrows, Ageing, Makeup, Blush, SunDamage, Skin, Lipstick, MolesFreckles, ChestHair, BodyBlemishes, DenseBodyBlemishes }
    public enum HeadOverlayColorType { Default, Colors1, Colors2, NoColor }
    public enum PedFaceFeature { NoseWidth, NoseHeight, NoseDepth, NoseRidge, NoseTip, NoseBroken, BrowHeight, BrowDepth, CheekboneHeight, CheekboneOut, CheekPlumpness, EyeSize, LipSize, JawWidth, JawRounded, ChinHeight, ChinOut, ChinPointy, ChinIndent, NeckWidth }

    public struct Component { public int drawableId; public int textureId; public int paletteId; [XmlIgnore] public int drawableNumber; public bool action; }
    public struct Prop { public int drawableId; public int textureId; [XmlIgnore] public int drawableNumber; public bool attach; public bool action; }
    public struct HeadOverlay { [XmlIgnore] public int overlayNumber; public int overlayValue; public float opacity; public int colorType; public int firstColor; public int secondColor; public bool overlayAction; public bool colorAction; }
    public struct OtherColors { public int eyeColorId; public int hairColorId; public int hairHighlightColorID; public bool eyeAction; public bool hairAction; }
    public struct HeadBlend { [XmlIgnore] public int faceNumber; public int shapeFirstID; public int shapeSecondID; public int shapeThirdID; public int skinFirstID; public int skinSecondID; public int skinThirdID; public float shapeMix; public float skinMix; public float thirdMix; public bool isParent; public bool action; }
    public struct FaceFeature { public float featureValue; public bool action; }
    public struct WeaponData { public uint weaponHash; public bool InUse; public int tint; public int ammo; public int ammoInClip; public int maxComponents; public List<uint> weaponComponent; }
    public struct Tattoos { public string collectionName; public string overlayName; public bool action; }
    public struct Badges { public string collectionName; public string overlayName; public bool action; }

    public static readonly string[] FEMALE_NAME = new string[] { "AmandaTownley", "TracyDisanto", "Patricia" };
    public static readonly string[] MALE_NAME = new string[] { "Michael", "Franklin", "Trevor" };
    public static readonly string[] COP_NAME = new string[] { "Cop01SMY", "Sheriff01SFY", "Sheriff01SMY", "HighwayCop01SMY", "Cop01SFY", "Armymech01SMY" };
    public static readonly string[] LSFD_PARAMEDIC_NAME = new string[] { "Fireman01SMY", "Paramedic01SMM" };
    public static readonly string[] ARMY_NAME = new string[] { "Armymech01SMY", "Marine01SMM", "Marine01SMY", "Marine02SMM", "Marine02SMY", "Marine03SMY" };
    public static readonly string[] PLAYER_NAME = new string[] { "Michael", "Franklin", "Trevor" };
    public static readonly string[] FREEMODE_NAME = new string[] { "FreemodeFemale01", "FreemodeMale01" };
    public static readonly string SKIN_PATH = "scripts\\CustomPeds\\Skin";
    public static readonly string[] FEMALE_VOICE_NAME = new string[19]
    {
        "s_f_y_hooker_01_white_full_01", "s_f_y_hooker_01_white_full_02", "s_f_y_hooker_01_white_full_03",
        "s_f_y_hooker_02_white_full_01", "s_f_y_hooker_02_white_full_02", "s_f_y_hooker_02_white_full_03",
        "s_f_y_hooker_03_black_full_01", "s_f_y_hooker_03_black_full_03",
        "s_f_m_genericcheapworker_01_latino_mini_01", "s_f_m_genericcheapworker_01_latino_mini_02", "s_f_m_genericcheapworker_01_latino_mini_03",
        "s_f_y_genericcheapworker_01_black_mini_01", "s_f_y_genericcheapworker_01_black_mini_02",
        "s_f_y_genericcheapworker_01_latino_mini_01", "s_f_y_genericcheapworker_01_latino_mini_02", "s_f_y_genericcheapworker_01_latino_mini_03", "s_f_y_genericcheapworker_01_latino_mini_04",
        "s_f_y_genericcheapworker_01_white_mini_01", "s_f_y_genericcheapworker_01_white_mini_02"
    };
    public static readonly string[] MALE_VOICE_NAME = new string[29]
    {
        "a_m_m_genericmale_01_white_mini_01", "a_m_m_genericmale_01_white_mini_02", "a_m_m_genericmale_01_white_mini_03", "a_m_m_genericmale_01_white_mini_04",
        "s_m_m_genericcheapworker_01_latino_mini_01", "s_m_m_genericcheapworker_01_latino_mini_02", "s_m_m_genericcheapworker_01_latino_mini_03", "s_m_m_genericcheapworker_01_latino_mini_04",
        "s_m_m_genericmarine_01_latino_mini_01", "s_m_m_genericmarine_01_latino_mini_02",
        "s_m_m_genericmechanic_01_black_mini_01", "s_m_m_genericmechanic_01_black_mini_02",
        "s_m_m_genericpostworker_01_black_mini_01", "s_m_m_genericpostworker_01_black_mini_02",
        "s_m_m_genericpostworker_01_white_mini_01", "s_m_m_genericpostworker_01_white_mini_02",
        "s_m_y_genericcheapworker_01_black_mini_01", "s_m_y_genericcheapworker_01_black_mini_02",
        "s_m_y_genericcheapworker_01_white_mini_01",
        "s_m_y_genericmarine_01_black_mini_01", "s_m_y_genericmarine_01_black_mini_02",
        "s_m_y_genericmarine_01_white_mini_01", "s_m_y_genericmarine_01_white_mini_02",
        "s_m_y_genericworker_01_black_mini_01", "s_m_y_genericworker_01_black_mini_02",
        "s_m_y_genericworker_01_latino_mini_01", "s_m_y_genericworker_01_latino_mini_02",
        "s_m_y_genericworker_01_white_mini_01", "s_m_y_genericworker_01_white_mini_02"
    };
    public static readonly int[] HEAD_OVERLAY_CAN_EDIT_COLOR = new int[6] { 1, 2, 4, 5, 8, 10 };
    public static readonly int HEAD_OVERLAY_COLOR_NUM = 64;
    public static readonly int OTHER_COLOR_HAIR_NUM = 64;
    public static readonly int OTHER_COLOR_EYE_NUM = 32;
    public static readonly string[] FACE_FEATURE = new string[20]
    {
        TextSetting.ffs_ListItem_NoseWidth,
        TextSetting.ffs_ListItem_NoseHeight,
        TextSetting.ffs_ListItem_NoseDepth,
        TextSetting.ffs_ListItem_NoseRidge,
        TextSetting.ffs_ListItem_NoseTip,
        TextSetting.ffs_ListItem_NoseBroken,
        TextSetting.ffs_ListItem_BrowHeight,
        TextSetting.ffs_ListItem_BrowDepth,
        TextSetting.ffs_ListItem_CheekboneHeight,
        TextSetting.ffs_ListItem_CheekboneOut,
        TextSetting.ffs_ListItem_CheekPlumpness,
        TextSetting.ffs_ListItem_EyeSize,
        TextSetting.ffs_ListItem_LipSize,
        TextSetting.ffs_ListItem_JawWidth,
        TextSetting.ffs_ListItem_JawRounded,
        TextSetting.ffs_ListItem_ChinHeight,
        TextSetting.ffs_ListItem_ChinOut,
        TextSetting.ffs_ListItem_ChinPointy,
        TextSetting.ffs_ListItem_ChinIndent,
        TextSetting.ffs_ListItem_NeckWidth
    };

    public Component[] Components = new Component[12];
    public Prop[] Props = new Prop[8];
    public HeadOverlay[] Head_Overlay = new HeadOverlay[13];
    public HeadBlend Head_Blend;
    public OtherColors Other_Colors;
    public FaceFeature[] Face_Feature = new FaceFeature[20];
    public Tattoos[][] Tattoo = new Tattoos[6][];
    public Badges[][] Badge = new Badges[6][];
    [XmlIgnore] public List<WeaponData> Weaponry;
    [XmlIgnore] public int[][] ComponentsTextureData = new int[12][];
    [XmlIgnore] public int[][] PropsTextureData = new int[8][];
    [XmlIgnore] public List<Decoration.Collection>[] TattooData;
    [XmlIgnore] public List<Decoration.Collection>[] BadgeData;
    public string ModelName;
    public string Gender;
    public string Voice;
    public bool IsAddonPed;
    private Ped Character;

    public Skin() { }
    public Skin(Ped _character, bool isAddonPed)
    {
        Character = _character;
        Gender = Character.Gender.ToString();
        Voice = string.Empty;
        IsAddonPed = isAddonPed;
        ModelName = Origin.GetPedModelName(Character.Model);
        for (int i = 0; i < 6; i++)
        {
            Tattoo[i] = new Tattoos[4];
            Badge[i] = new Badges[4];
            for (int j = 0; j < 4; j++)
            {
                Tattoo[i][j] = default(Tattoos);
                Badge[i][j] = default(Badges);
            }
        }
    }

    public static bool SkinFileSave(Origin origin, string name, string fullName = "")
    {
        try
        {
            if (fullName == "")
            {
                if (!MakeFilenameValid(ref name)) return false;
                XmlSerializer xmlSerializer = new XmlSerializer(origin.skin.GetType());
                using XmlTextWriter xmlTextWriter = new XmlTextWriter($"{SKIN_PATH}\\{origin.skin.Gender}\\{name}.skin", Encoding.UTF8);
                xmlTextWriter.Formatting = Formatting.Indented;
                xmlSerializer.Serialize(xmlTextWriter, origin.skin);
            }
            else
            {
                File.Delete(fullName);
                XmlSerializer xmlSerializer2 = new XmlSerializer(origin.skin.GetType());
                using XmlTextWriter xmlTextWriter2 = new XmlTextWriter($"{SKIN_PATH}\\{origin.skin.Gender}\\{name}.skin", Encoding.UTF8);
                xmlTextWriter2.Formatting = Formatting.Indented;
                xmlSerializer2.Serialize(xmlTextWriter2, origin.skin);
            }
        }
        catch (Exception ex)
        {
            LogHelper.WriteException(ex, "SkinFileSave - 保存皮肤文件");
            return false;
        }
        return true;
    }

    public static bool SkinFileLoad(ref Origin origin, string fullName, bool isClone = false)
    {
        try
        {
            if (IsXml(fullName))
            {
                XmlSerializer xmlSerializer = new XmlSerializer(origin.skin.GetType());
                using XmlTextReader xmlReader = new XmlTextReader(fullName);
                SetSkinAll(ref origin, (Skin)xmlSerializer.Deserialize(xmlReader), isClone);
            }
        }
        catch (Exception ex)
        {
            LogHelper.WriteException(ex, "SkinFileLoad - 加载皮肤文件");
            return false;
        }
        return true;
    }

    private static void SetSkinAll(ref Origin origin, Skin skin, bool isClone = false)
    {
        Ped character = skin.Character;
        if (origin.Member == Main.Member.P2)
        {
            // 若当前 P2 未初始化，通过 ReBuildP2 创建；并在 Follow 时加入组
            Main.ReBuildP2(Main.P2.Character, skin.ModelName, skin.IsAddonPed);
            character = Main.P2.Character;
            if (character != null && !Game.Player.Character.PedGroup.Contains(character) && Main.P2.Follow)
            {
                Main.P1.Character.PedGroup.Add(character, leader: false);
            }
        }
        else if (origin.Member == Main.Member.P1 && !isClone)
        {
            Main.ChangePlayerModel(skin.ModelName, skin.IsAddonPed);
            origin.BuildPedData(Game.Player.Character, Main.Member.P1, skin.IsAddonPed);
            character = Main.P1.Character;
            character.SetDefaultClothes();
        }
        else if (origin.Member == Main.Member.Clone && isClone)
        {
            if (Main.Clone.Character != null)
            {
                Main.Clone.Character.MarkAsNoLongerNeeded();
                Main.Clone.Character.Delete();
            }
            Ped ped = Main.CreatePed(skin.ModelName, skin.IsAddonPed);
            if (ped == null) return;
            Main.Clone.Character = ped;
            Main.Clone.Character.BlockPermanentEvents = true;
            Main.Clone.Character.IsPersistent = true;
            Main.Clone.BuildPedData(Main.Clone.Character, Main.Member.Clone, skin.IsAddonPed);
            character = Main.Clone.Character;
            character.SetDefaultClothes();
        }
        for (int i = 0; i < 12; i++)
        {
            if (skin.Components[i].action)
            {
                SkinHelper.SetPedComponentVariation(character, i, skin.Components[i].drawableId, skin.Components[i].textureId, skin.Components[i].paletteId);
            }
        }
        SkinHelper.ClearAllPedProps(character);
        for (int j = 0; j < 8; j++)
        {
            if (skin.Props[j].action)
            {
                SkinHelper.SetPedPropIndex(character, j, skin.Props[j].drawableId, skin.Props[j].textureId, skin.Props[j].attach);
            }
        }
        SkinHelper.ClearPedDecorations(character);
        for (int k = 0; k < 6; k++)
        {
            for (int l = 0; l < 4; l++)
            {
                if (skin.Tattoo[k][l].action)
                {
                    SkinHelper.SetPedDecoration(character, skin.Tattoo[k][l].collectionName, skin.Tattoo[k][l].overlayName);
                }
            }
        }
        for (int m = 0; m < 6; m++)
        {
            for (int n = 0; n < 4; n++)
            {
                if (skin.Badge[m][n].action)
                {
                    SkinHelper.SetPedDecoration(character, skin.Badge[m][n].collectionName, skin.Badge[m][n].overlayName);
                }
            }
        }
        if (skin.Head_Blend.action)
        {
            SkinHelper.SetPedHeadBlendData(character, skin.Head_Blend.shapeFirstID, skin.Head_Blend.shapeSecondID, skin.Head_Blend.shapeThirdID, skin.Head_Blend.skinFirstID, skin.Head_Blend.skinSecondID, skin.Head_Blend.skinThirdID, skin.Head_Blend.shapeMix, skin.Head_Blend.skinMix, skin.Head_Blend.thirdMix, skin.Head_Blend.isParent);
            for (int num = 0; num < 20; num++)
            {
                if (skin.Face_Feature[num].action)
                {
                    SkinHelper.SetPedFaceFeature(character, num, skin.Face_Feature[num].featureValue);
                }
            }
            for (int num2 = 0; num2 < 13; num2++)
            {
                if (skin.Head_Overlay[num2].overlayAction)
                {
                    SkinHelper.SetPedHeadOverlayValue(character, num2, skin.Head_Overlay[num2].overlayValue, skin.Head_Overlay[num2].opacity);
                    if (skin.Head_Overlay[num2].colorAction)
                    {
                        SkinHelper.SetPedHeadOverlayColor(character, num2, skin.Head_Overlay[num2].colorType, skin.Head_Overlay[num2].firstColor, skin.Head_Overlay[num2].secondColor);
                    }
                }
            }
            if (skin.Other_Colors.eyeAction)
            {
                SkinHelper.SetPedEyeColor(character, skin.Other_Colors.eyeColorId);
            }
            if (skin.Other_Colors.hairAction)
            {
                SkinHelper.SetPedHairColor(character, skin.Other_Colors.hairColorId, skin.Other_Colors.hairHighlightColorID);
            }
        }
        if (!string.IsNullOrEmpty(skin.Voice))
        {
            character.SetVoice(skin.Voice);
        }
        origin.skin = skin;
        origin.skin.Character = character;
    }

    private static bool IsXml(string Path)
    {
        try { new XmlDocument().Load(Path); return true; }
        catch { return false; }
    }

    private static bool MakeFilenameValid(ref string filename)
    {
        filename ??= string.Empty;
        if (filename.EndsWith(".")) { filename = Regex.Replace(filename, "\\.+$", ""); }
        if (filename.IndexOf('.') >= 0) { filename = filename.Substring(0, filename.IndexOf('.')); }
        if (filename.Length == 0) { filename = string.Empty; }
        if (filename.Length > 245) { filename = string.Empty; }
        if (filename.Replace(" ", "") == string.Empty) { filename = string.Empty; }
        char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
        foreach (char oldChar in invalidFileNameChars) { filename = filename.Replace(oldChar, '_'); }
        if (filename != string.Empty) { return true; }
        return false;
    }

    public void GetComponentsValue()
    {
        foreach (int value in Enum.GetValues(typeof(PedComponents)))
        {
            Components[value].drawableId = SkinHelper.GetPedDrawableVariation(Character, value);
            Components[value].textureId = SkinHelper.GetPedTextureVariation(Character, value);
            Components[value].paletteId = SkinHelper.GetPedPaletteVariation(Character, value);
        }
    }

    public void GetPropsValue()
    {
        foreach (int value in Enum.GetValues(typeof(PedProps)))
        {
            Props[value].drawableId = SkinHelper.GetPedPropIndex(Character, value);
            Props[value].textureId = SkinHelper.GetPedPropTextureIndex(Character, value);
        }
    }

    public void GetComponentsVariableNumber()
    {
        foreach (int value in Enum.GetValues(typeof(PedComponents)))
        {
            Components[value].drawableNumber = SkinHelper.GetPedDrawableNumber(Character, value);
            ComponentsTextureData[value] = new int[Components[value].drawableNumber];
            for (int i = 0; i < Components[value].drawableNumber; i++)
            {
                ComponentsTextureData[value][i] = SkinHelper.GetPedTextureNumber(Character, value, i);
            }
        }
    }

    public void GetPropsVariableNumber()
    {
        foreach (int value in Enum.GetValues(typeof(PedProps)))
        {
            Props[value].drawableNumber = SkinHelper.GetPedPropDrawableNumber(Character, value);
            PropsTextureData[value] = new int[Props[value].drawableNumber];
            for (int i = 0; i < Props[value].drawableNumber; i++)
            {
                PropsTextureData[value][i] = SkinHelper.GetPedPropTextureNumber(Character, value, i);
            }
        }
    }

    public void GetHeadBlendFaceNumber()
    {
        Head_Blend.faceNumber = 0;
        for (int i = 0; i < 4; i++)
        {
            Head_Blend.faceNumber += SkinHelper.GetNumParentPedsOfType(i);
        }
    }

    public void GetHeadOverlayVariableNumber()
    {
        foreach (int value in Enum.GetValues(typeof(PedHeadOverlay)))
        {
            Head_Overlay[value].overlayNumber = SkinHelper.GetNumHeadOverlayValue(value);
        }
    }

    public void GetDecorationData(Decoration.Type type)
    {
        var list = Decoration.Collection.GetCollectionList(type);
        switch (type)
        {
            case Decoration.Type.TYPE_TATTOO:
                TattooData = new List<Decoration.Collection>[6];
                for (int j = 0; j < 6; j++)
                {
                    TattooData[j] = [];
                    foreach (Decoration.Collection item in list)
                    {
                        Decoration.Collection collectionClassify = Decoration.Collection.GetCollectionClassify(item, Character.Gender, (Decoration.Zone)j);
                        if (collectionClassify.overlay.Count > 0)
                        {
                            TattooData[j].Add(collectionClassify);
                        }
                    }
                }
                break;
            case Decoration.Type.TYPE_BADGE:
                BadgeData = new List<Decoration.Collection>[6];
                for (int i = 0; i < 6; i++)
                {
                    BadgeData[i] = [];
                    foreach (Decoration.Collection item2 in list)
                    {
                        Decoration.Collection collectionClassify = Decoration.Collection.GetCollectionClassify(item2, Character.Gender, (Decoration.Zone)i);
                        if (collectionClassify.overlay.Count > 0)
                        {
                            BadgeData[i].Add(collectionClassify);
                        }
                    }
                }
                break;
        }
    }

    public void ClearDecoration(Decoration.Type type, int gid, Decoration.Zone zone = Decoration.Zone.ZONE_NONE)
    {
        if (type == Decoration.Type.TYPE_TATTOO)
        {
            if (zone == Decoration.Zone.ZONE_NONE)
            {
                SkinHelper.ClearPedDecorations(Character);
                for (int i = 0; i < 6; i++)
                {
                    Tattoo[i][gid].collectionName = (Tattoo[i][gid].overlayName = string.Empty);
                    Tattoo[i][gid].action = false;
                }
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 4; k++)
                    {
                        if (k != gid)
                        {
                            SkinHelper.SetPedDecoration(Character, Tattoo[j][k].collectionName, Tattoo[j][k].overlayName);
                        }
                    }
                }
                for (int l = 0; l < 6; l++)
                {
                    for (int m = 0; m < 4; m++)
                    {
                        SkinHelper.SetPedDecoration(Character, Badge[l][m].collectionName, Badge[l][m].overlayName);
                    }
                }
            }
            if (zone < Decoration.Zone.ZONE_UNKNOWN)
            {
                Tattoo[(int)zone][gid].collectionName = (Tattoo[(int)zone][gid].overlayName = string.Empty);
                Tattoo[(int)zone][gid].action = false;
                SkinHelper.ClearPedDecorations(Character);
                for (int n = 0; n < 6; n++)
                {
                    for (int num = 0; num < 4; num++)
                    {
                        if ((num == gid && n != (int)zone) || num != gid)
                        {
                            SkinHelper.SetPedDecoration(Character, Tattoo[n][num].collectionName, Tattoo[n][num].overlayName);
                        }
                    }
                }
                for (int num2 = 0; num2 < 6; num2++)
                {
                    for (int num3 = 0; num3 < 4; num3++)
                    {
                        SkinHelper.SetPedDecoration(Character, Badge[num2][num3].collectionName, Badge[num2][num3].overlayName);
                    }
                }
            }
        }
        if (type != Decoration.Type.TYPE_BADGE)
        {
            return;
        }
        if (zone == Decoration.Zone.ZONE_NONE)
        {
            SkinHelper.ClearPedDecorations(Character);
            for (int num4 = 0; num4 < 6; num4++)
            {
                Badge[num4][gid].collectionName = (Badge[num4][gid].overlayName = string.Empty);
                Badge[num4][gid].action = false;
            }
            for (int num5 = 0; num5 < 6; num5++)
            {
                for (int num6 = 0; num6 < 4; num6++)
                {
                    if (num6 != gid)
                    {
                        SkinHelper.SetPedDecoration(Character, Badge[num5][num6].collectionName, Badge[num5][num6].overlayName);
                    }
                }
            }
            for (int num7 = 0; num7 < 6; num7++)
            {
                for (int num8 = 0; num8 < 4; num8++)
                {
                    SkinHelper.SetPedDecoration(Character, Tattoo[num7][num8].collectionName, Tattoo[num7][num8].overlayName);
                }
            }
        }
        if (zone >= Decoration.Zone.ZONE_UNKNOWN)
        {
            return;
        }
        Badge[(int)zone][gid].collectionName = (Badge[(int)zone][gid].overlayName = string.Empty);
        Badge[(int)zone][gid].action = false;
        SkinHelper.ClearPedDecorations(Character);
        for (int num9 = 0; num9 < 6; num9++)
        {
            for (int num10 = 0; num10 < 4; num10++)
            {
                if ((num10 == gid && num9 != (int)zone) || num10 != gid)
                {
                    SkinHelper.SetPedDecoration(Character, Badge[num9][num10].collectionName, Badge[num9][num10].overlayName);
                }
            }
        }
        for (int num11 = 0; num11 < 6; num11++)
        {
            for (int num12 = 0; num12 < 4; num12++)
            {
                SkinHelper.SetPedDecoration(Character, Tattoo[num11][num12].collectionName, Tattoo[num11][num12].overlayName);
            }
        }
    }

    public List<WeaponData> GetWeaponsData()
    {
        Weaponry = [];
        List<uint> list = [];
        uint hash = (uint)Character.Weapons.Current.Hash;
        foreach (WeaponHash value in Enum.GetValues(typeof(WeaponHash)))
        {
            if (Character.Weapons.HasWeapon(value))
            {
                list.Add((uint)value);
            }
        }
        foreach (uint item2 in list)
        {
            WeaponData item = new WeaponData
            {
                weaponComponent = [],
                InUse = hash == item2
            };
            Character.Weapons.Select((WeaponHash)item2, equipNow: true);
            item.weaponHash = item2;
            item.ammo = Character.Weapons.Current.Ammo;
            item.ammoInClip = Character.Weapons.Current.AmmoInClip;
            item.tint = (int)Character.Weapons.Current.Tint;
            // SHVDN3: enumerate all component hashes and collect installed ones
            foreach (WeaponComponentHash comp in Enum.GetValues(typeof(WeaponComponentHash)))
            {
                // HAS_PED_GOT_WEAPON_COMPONENT(ped, weaponHash, componentHash)
                if (Function.Call<bool>((Hash)0xC593212475FAE340ul, Character, item2, (uint)comp))
                {
                    item.weaponComponent.Add((uint)comp);
                }
            }
            item.maxComponents = item.weaponComponent.Count;
            Weaponry.Add(item);
        }
        Character.Weapons.Select((WeaponHash)hash, equipNow: true);
        return Weaponry;
    }

    public void SetWeapons(List<WeaponData> _weaponry)
    {
        Character.Weapons.RemoveAll();
        foreach (WeaponData item in _weaponry)
        {
            Character.Weapons.Give((WeaponHash)item.weaponHash, item.ammo, equipNow: true, isAmmoLoaded: false);
            Character.Weapons.Current.AmmoInClip = item.ammoInClip;
            Character.Weapons.Current.Tint = (WeaponTint)item.tint;
            Character.Weapons.Select((WeaponHash)item.weaponHash, equipNow: true);
            for (int i = 0; i < item.weaponComponent.Count; i++)
            {
                // GIVE_WEAPON_COMPONENT_TO_PED(ped, weaponHash, componentHash)
                Function.Call((Hash)0xD966D51AA5B28BB9ul, Character, item.weaponHash, item.weaponComponent[i]);
            }
        }
        foreach (WeaponData item2 in _weaponry)
        {
            if (item2.InUse)
            {
                Character.Weapons.Select((WeaponHash)item2.weaponHash, equipNow: true);
            }
        }
    }

    public static string[] GetAddonPedsLoadName()
    {
        string filename = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "\\Rockstar Games\\GTA V\\UserMods\\ap_m.xml";
        try
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(filename);
            XmlNodeList xmlNodeList = xmlDocument.SelectNodes("/CPedModelInfo__InitDataList/InitDatas/Item");
            List<string> list = [];
            if (xmlNodeList != null)
                foreach (XmlNode item in xmlNodeList)
                {
                    list.Add(item["Name"]?.InnerText);
                }

            return list.ToArray();
        }
        catch (Exception)
        {
            Notification.PostTicker("Could not read AddonPeds XML list.", true, false);
        }
        return [];
    }

    public static void TryConvertAddonPedName(ref string name)
    {
        string numHash = name;
        string[] addonPedsLoadName = GetAddonPedsLoadName();
        if (addonPedsLoadName != null && numHash != null && TestStringToInt(numHash))
        {
            numHash = Array.Find(addonPedsLoadName, n => Origin.GetHash(n) == Convert.ToUInt32(numHash));
        }
        if (!string.IsNullOrEmpty(numHash))
        {
            name = numHash;
        }
    }

    private static bool TestStringToInt(string str)
    {
        try {
            Convert.ToUInt32(str);
            return true; } catch { return false; }
    }
}


